Domine la API Temporal de JavaScript para el manejo moderno de fechas y horas. Aprenda a reemplazar los objetos Date heredados.
API Temporal de JavaScript: Manipulación Moderna de Fechas y Horas
El objeto Date de JavaScript ha sido durante mucho tiempo una fuente de frustración para los desarrolladores. Su mutabilidad, la falta de soporte de zona horaria incorporado y su API torpe han llevado a innumerables bibliotecas y soluciones alternativas. Afortunadamente, la API Temporal tiene como objetivo abordar estas deficiencias, proporcionando una solución moderna, intuitiva y consciente de la zona horaria para la manipulación de fechas y horas en JavaScript.
¿Qué es la API Temporal?
La API Temporal es un nuevo objeto global, Temporal, que proporciona una forma moderna y estandarizada de trabajar con fechas y horas en JavaScript. Está diseñada para reemplazar el objeto Date heredado, ofreciendo mejoras significativas en términos de diseño de la API, inmutabilidad, soporte de zona horaria y usabilidad general. Es parte de la propuesta ECMAScript y se está implementando en los principales motores de JavaScript.
Beneficios clave de la API Temporal:
- Inmutabilidad: Los objetos temporales son inmutables, lo que significa que las operaciones en ellos devuelven nuevos objetos en lugar de modificar el original. Esto ayuda a prevenir efectos secundarios inesperados y facilita la comprensión del código.
- API clara: La API está diseñada para ser más intuitiva y consistente que el objeto
Dateheredado. - Soporte de zona horaria: Temporal proporciona un soporte robusto para zonas horarias, lo que le permite trabajar con fechas y horas en diferentes ubicaciones de todo el mundo.
- Soporte de calendario: Más allá del calendario gregoriano, la API permite el uso de otros sistemas de calendario, lo que facilita las aplicaciones globales.
- Manejo de segundos intercalares: La API Temporal tiene en cuenta los segundos intercalares, proporcionando cálculos de tiempo más precisos.
Primeros pasos con Temporal
Si bien la API Temporal aún está en desarrollo y aún no es totalmente compatible con todos los navegadores y entornos Node.js, puede usar un polyfill para comenzar a experimentar con ella hoy. Puede instalar el polyfill a través de npm:
npm install @js-temporal/polyfill
Luego, importe el polyfill en su código JavaScript:
import { Temporal } from '@js-temporal/polyfill';
Una vez que el polyfill esté instalado, puede comenzar a usar el objeto Temporal y sus diversas clases.
Clases centrales de Temporal
La API Temporal proporciona varias clases clave para trabajar con fechas y horas:
Temporal.PlainDate: Representa una fecha de calendario (año, mes y día) sin ninguna información de zona horaria o hora del día.Temporal.PlainTime: Representa una hora del día (hora, minuto, segundo y fracción de segundo) sin ninguna información de fecha o zona horaria.Temporal.PlainDateTime: Representa una fecha y hora sin ninguna información de zona horaria.Temporal.ZonedDateTime: Representa una fecha y hora con una zona horaria específica.Temporal.Instant: Representa un punto específico en el tiempo, medido en nanosegundos desde la época de Unix (1 de enero de 1970, a las 00:00:00 UTC).Temporal.TimeZone: Representa una zona horaria.Temporal.Duration: Representa una duración de tiempo, como horas, minutos o segundos.Temporal.Now: Proporciona acceso a la fecha y hora actuales.
Trabajar con PlainDate
La clase Temporal.PlainDate representa una fecha sin ninguna información de zona horaria o hora del día. Es útil para representar cumpleaños, aniversarios u otros eventos basados en fechas.
Creación de un PlainDate:
const plainDate = Temporal.PlainDate.from({ year: 2024, month: 10, day: 26 });
console.log(plainDate.toString()); // Output: 2024-10-26
También puede crear un PlainDate a partir de una cadena en formato ISO 8601:
const plainDateFromString = Temporal.PlainDate.from('2024-12-25');
console.log(plainDateFromString.toString()); // Output: 2024-12-25
Acceso a los componentes de la fecha:
const year = plainDate.year; // 2024
const month = plainDate.month; // 10
const day = plainDate.day; // 26
const dayOfWeek = plainDate.dayOfWeek; // Día de la semana (1-7, lunes-domingo)
const dayOfYear = plainDate.dayOfYear; // Día del año (1-366)
const daysInMonth = plainDate.daysInMonth; // Número de días en el mes
const isLeapYear = plainDate.isLeapYear; // Booleano que indica si el año es bisiesto
Suma y resta de días:
const nextDay = plainDate.add({ days: 1 });
console.log(nextDay.toString()); // Output: 2024-10-27
const previousWeek = plainDate.subtract({ weeks: 1 });
console.log(previousWeek.toString()); // Output: 2024-10-19
Comparación de fechas:
const anotherDate = Temporal.PlainDate.from({ year: 2024, month: 11, day: 15 });
if (plainDate.equals(anotherDate)) {
console.log('Las fechas son iguales');
} else if (plainDate.lessThan(anotherDate)) {
console.log('plainDate es anterior a anotherDate');
} else {
console.log('plainDate es posterior a anotherDate');
}
// Output: plainDate es anterior a anotherDate
Trabajar con PlainTime
La clase Temporal.PlainTime representa una hora del día sin ninguna información de fecha o zona horaria. Es útil para representar horarios de apertura, horarios de reuniones u otros eventos basados en el tiempo.
Creación de un PlainTime:
const plainTime = Temporal.PlainTime.from({ hour: 14, minute: 30, second: 0 });
console.log(plainTime.toString()); // Output: 14:30:00
También puede crear un PlainTime a partir de una cadena en formato ISO 8601:
const plainTimeFromString = Temporal.PlainTime.from('09:00:00');
console.log(plainTimeFromString.toString()); // Output: 09:00:00
Acceso a los componentes de tiempo:
const hour = plainTime.hour; // 14
const minute = plainTime.minute; // 30
const second = plainTime.second; // 0
const millisecond = plainTime.millisecond; // 0
const microsecond = plainTime.microsecond; // 0
const nanosecond = plainTime.nanosecond; // 0
Suma y resta de tiempo:
const laterTime = plainTime.add({ minutes: 15 });
console.log(laterTime.toString()); // Output: 14:45:00
const earlierTime = plainTime.subtract({ hours: 1 });
console.log(earlierTime.toString()); // Output: 13:30:00
Comparación de tiempos:
const anotherTime = Temporal.PlainTime.from({ hour: 15, minute: 0, second: 0 });
if (plainTime.equals(anotherTime)) {
console.log('Los tiempos son iguales');
} else if (plainTime.lessThan(anotherTime)) {
console.log('plainTime es anterior a anotherTime');
} else {
console.log('plainTime es posterior a anotherTime');
}
// Output: plainTime es anterior a anotherTime
Trabajar con PlainDateTime
La clase Temporal.PlainDateTime representa una fecha y hora sin ninguna información de zona horaria. Combina la funcionalidad de PlainDate y PlainTime.
Creación de un PlainDateTime:
const plainDateTime = Temporal.PlainDateTime.from({ year: 2024, month: 10, day: 26, hour: 14, minute: 30, second: 0 });
console.log(plainDateTime.toString()); // Output: 2024-10-26T14:30:00
También puede crear un PlainDateTime a partir de una cadena en formato ISO 8601:
const plainDateTimeFromString = Temporal.PlainDateTime.from('2024-12-25T09:00:00');
console.log(plainDateTimeFromString.toString()); // Output: 2024-12-25T09:00:00
Acceso a los componentes de fecha y hora:
const year = plainDateTime.year; // 2024
const month = plainDateTime.month; // 10
const day = plainDateTime.day; // 26
const hour = plainDateTime.hour; // 14
const minute = plainDateTime.minute; // 30
const second = plainDateTime.second; // 0
Suma y resta de fechas y horas:
const nextDayAndTime = plainDateTime.add({ days: 1, hours: 2 });
console.log(nextDayAndTime.toString()); // Output: 2024-10-27T16:30:00
const previousWeekAndTime = plainDateTime.subtract({ weeks: 1, minutes: 30 });
console.log(previousWeekAndTime.toString()); // Output: 2024-10-19T14:00:00
Conversión a PlainDate y PlainTime:
const plainDateFromDateTime = plainDateTime.toPlainDate();
console.log(plainDateFromDateTime.toString()); // Output: 2024-10-26
const plainTimeFromDateTime = plainDateTime.toPlainTime();
console.log(plainTimeFromDateTime.toString()); // Output: 14:30:00
Trabajar con ZonedDateTime
La clase Temporal.ZonedDateTime representa una fecha y hora con una zona horaria específica. Esto es crucial para las aplicaciones que necesitan manejar fechas y horas en diferentes lugares del mundo. A diferencia del objeto Date heredado, Temporal proporciona soporte de zona horaria incorporado.
Creación de un ZonedDateTime:
const zonedDateTime = Temporal.ZonedDateTime.from({ year: 2024, month: 10, day: 26, hour: 14, minute: 30, second: 0, timeZone: 'America/Los_Angeles' });
console.log(zonedDateTime.toString()); // Output: 2024-10-26T14:30:00-07:00[America/Los_Angeles]
También puede crear un ZonedDateTime a partir de un Instant y una zona horaria:
const instant = Temporal.Instant.fromEpochSeconds(1666785000); // Ejemplo de marca de tiempo
const zonedDateTimeFromInstant = instant.toZonedDateTimeISO('Europe/London');
console.log(zonedDateTimeFromInstant.toString()); // La salida variará según el instante real, pero reflejará la fecha/hora en Europa/Londres
Acceso a los componentes de fecha y hora:
const year = zonedDateTime.year; // 2024
const month = zonedDateTime.month; // 10
const day = zonedDateTime.day; // 26
const hour = zonedDateTime.hour; // 14
const minute = zonedDateTime.minute; // 30
const second = zonedDateTime.second; // 0
const timeZone = zonedDateTime.timeZone; // Objeto Temporal.TimeZone
Conversión entre zonas horarias:
const newYorkDateTime = zonedDateTime.withTimeZone('America/New_York');
console.log(newYorkDateTime.toString()); // Output: 2024-10-26T17:30:00-04:00[America/New_York]
Manejo del horario de verano (DST):
Temporal maneja automáticamente las transiciones DST. Al sumar o restar tiempo, tiene en cuenta el DST, lo que garantiza resultados precisos. Por ejemplo, considere una reunión programada a través de la transición DST en Alemania:
const meetingStart = Temporal.ZonedDateTime.from({ year: 2024, month: 3, day: 31, hour: 2, minute: 30, timeZone: 'Europe/Berlin' });
const meetingEnd = meetingStart.add({ hours: 1 }); // Adding 1 hour
console.log(meetingEnd.toString()); // Output: 2024-03-31T03:30:00+02:00[Europe/Berlin]. Notice the offset changes due to DST
Trabajar con Instant
La clase Temporal.Instant representa un punto específico en el tiempo, medido en nanosegundos desde la época de Unix. Es útil para almacenar y comparar momentos exactos en el tiempo.
Creación de un Instant:
const instant = Temporal.Instant.fromEpochSeconds(1666785000); // Ejemplo de marca de tiempo Unix en segundos
console.log(instant.toString()); // La salida será una representación de cadena ISO de ese instante
Conversión a ZonedDateTime:
const zonedDateTimeFromInstant = instant.toZonedDateTimeISO('America/Los_Angeles');
console.log(zonedDateTimeFromInstant.toString()); // Output: Fecha y hora en America/Los_Angeles correspondiente al instante
Comparación de Instantes:
const anotherInstant = Temporal.Instant.fromEpochSeconds(1666790000);
if (instant.equals(anotherInstant)) {
console.log('Los instantes son iguales');
} else if (instant.lessThan(anotherInstant)) {
console.log('instant es anterior a anotherInstant');
} else {
console.log('instant es posterior a anotherInstant');
}
// Output: instant es anterior a anotherInstant
Trabajar con Duration
La clase Temporal.Duration representa una duración de tiempo, como horas, minutos o segundos. Es útil para calcular la diferencia entre dos fechas u horas.
Creación de un Duration:
const duration = Temporal.Duration.from({ hours: 2, minutes: 30 });
console.log(duration.toString()); // Output: PT2H30M
Cálculo de la diferencia entre fechas/horas:
const startDate = Temporal.PlainDateTime.from({ year: 2024, month: 1, day: 1, hour: 0, minute: 0, second: 0 });
const endDate = Temporal.PlainDateTime.from({ year: 2024, month: 1, day: 3, hour: 12, minute: 30, second: 0 });
const difference = endDate.since(startDate);
console.log(difference.toString()); // Output: P2DT12H30M
// Acceder a los componentes de la duración
console.log(difference.days); // 2
console.log(difference.hours); // 12
console.log(difference.minutes); // 30
Agregar Duración a fechas/horas:
const newDate = startDate.add(duration);
console.log(newDate.toString()); // Output: 2024-01-03T02:30:00
Trabajar con calendarios
La API Temporal admite diferentes sistemas de calendario más allá del calendario gregoriano. Si bien aún no se implementa por completo en todos los polyfills y motores, la intención es permitir que las aplicaciones manejen fechas en calendarios específicos de varias culturas. Por ejemplo, para usar el calendario japonés (hipotéticamente, ya que la implementación aún está evolucionando):
// Este es un ejemplo conceptual, ya que el soporte del calendario aún está en desarrollo
// const japaneseDate = Temporal.PlainDate.from({ year: 2024, month: 10, day: 26, calendar: 'japanese' });
// console.log(japaneseDate.toString()); // Esperado: Salida formateada según el calendario japonés
Nota: El soporte del calendario es una característica en evolución de la API Temporal, y la funcionalidad completa aún no está disponible universalmente.
Ejemplos prácticos y casos de uso
La API Temporal ofrece una amplia gama de posibilidades para el manejo de fechas y horas en JavaScript. Aquí hay algunos ejemplos prácticos y casos de uso:
- Programación de citas: Cree una aplicación de programación que permita a los usuarios reservar citas en su zona horaria local. Temporal.ZonedDateTime facilita la conversión entre zonas horarias y el manejo de las transiciones DST. Para una clínica en Berlín que programa citas a nivel mundial:
- Cálculo de la edad: Determine la edad de un usuario en función de su fecha de nacimiento. PlainDate le permite representar la fecha de nacimiento sin ninguna información de zona horaria.
- Mostrar fechas y horas en diferentes formatos: Formatee las fechas y horas de acuerdo con la configuración regional del usuario. Si bien las funciones de internacionalización (Intl) son separadas, los objetos Temporal se pueden formatear fácilmente usando
toLocaleString()o métodos similares cuando se combinan con las funciones de la API Intl. - Seguimiento de la duración de los eventos: Calcule la duración de un evento y muéstrela en un formato legible por humanos. Duration le permite representar la diferencia de tiempo entre dos fechas u horas.
const appointmentTimeBerlin = Temporal.ZonedDateTime.from({ year: 2024, month: 11, day: 5, hour: 10, minute: 0, timeZone: 'Europe/Berlin' });
const appointmentTimeLA = appointmentTimeBerlin.withTimeZone('America/Los_Angeles');
console.log(`Hora de la cita en Berlín: ${appointmentTimeBerlin.toString()}`);
console.log(`Hora de la cita en Los Ángeles: ${appointmentTimeLA.toString()}`);
const birthDate = Temporal.PlainDate.from({ year: 1990, month: 5, day: 15 });
const today = Temporal.Now.plainDateISO();
const age = today.year - birthDate.year - (today.month < birthDate.month || (today.month === birthDate.month && today.day < birthDate.day) ? 1 : 0);
console.log(`Edad: ${age}`);
const zonedDateTimeNow = Temporal.Now.zonedDateTimeISO('en-GB');
console.log(zonedDateTimeNow.toLocaleString('en-GB'));
console.log(zonedDateTimeNow.toLocaleString('de-DE'));
const eventStart = Temporal.Instant.fromEpochSeconds(1700000000); // Ejemplo de marca de tiempo de inicio
const eventEnd = Temporal.Instant.fromEpochSeconds(1700005000); // Ejemplo de marca de tiempo final
const durationOfEvent = eventEnd.since(eventStart);
console.log(`Duración del evento: ${durationOfEvent.minutes} minutos`);
Mejores prácticas para usar la API Temporal
Aquí hay algunas mejores prácticas que debe tener en cuenta al usar la API Temporal:
- Usar inmutabilidad: Acepte la inmutabilidad de los objetos Temporal. Evite modificar objetos directamente. En su lugar, cree nuevos objetos usando métodos como
add,subtractywith. - Manejar las zonas horarias con cuidado: Tenga en cuenta las zonas horarias cuando trabaje con fechas y horas. Use
ZonedDateTimecuando necesite representar fechas y horas en una zona horaria específica. - Usar nombres de variables claros: Use nombres de variables descriptivos que indiquen claramente el tipo de objeto Temporal que se está utilizando (por ejemplo,
plainDate,zonedDateTime,duration). - Considere los polyfills: Debido a que Temporal aún es relativamente nuevo, asegúrese de un soporte suficiente mediante el uso de una biblioteca polyfill cuando sea necesario.
- Validar la entrada: Valide siempre la entrada del usuario para asegurarse de que las fechas y horas tengan el formato correcto.
Migración desde Date heredado
La migración desde el objeto Date heredado puede ser un proceso gradual. Considere estas estrategias:
- Adopción incremental: Comience a usar Temporal en código nuevo mientras mantiene
Dateen partes existentes de su aplicación. - Funciones de envoltura: Cree funciones de envoltura que conviertan entre objetos
Datey Temporal para facilitar la interoperabilidad durante la migración. - Pruebas exhaustivas: Pruebe la migración exhaustivamente para asegurarse de que todos los cálculos de fecha y hora sean precisos.
API Temporal vs. Moment.js
Moment.js era una biblioteca popular para la manipulación de fechas y horas en JavaScript, pero ahora se considera un proyecto heredado y está en modo de mantenimiento. La API Temporal proporciona una solución más moderna y estandarizada que aborda muchas de las deficiencias de Moment.js. Moment.js es mutable y carece de soporte de zona horaria nativo. La API Temporal es inmutable y tiene soporte de zona horaria nativo.
Conclusión
La API Temporal de JavaScript representa una mejora significativa con respecto al objeto Date heredado. Su inmutabilidad, API clara, soporte de zona horaria y soporte de calendario la convierten en una herramienta poderosa para manejar fechas y horas en las aplicaciones modernas de JavaScript. Si bien la adopción aún está creciendo, el uso de un polyfill le permite comenzar a aprovechar sus beneficios hoy. A medida que la API sea más ampliamente compatible, se espera que se convierta en la forma estándar de trabajar con fechas y horas en JavaScript.
Adopte la API Temporal y desbloquee una forma más eficiente y confiable de administrar fechas y horas en sus proyectos, asegurando que su aplicación maneje las zonas horarias y los cálculos globales con precisión.